/*
* Copyright (C) 2007, 2009, 2010, 2011, 2012 IsmAvatar <IsmAvatar@gmail.com>
* Copyright (C) 2007, 2008 Quadduc <quadduc@gmail.com>
*
* This file is part of LibMaker.
* LibMaker is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package org.lateralgm.libmaker;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import org.lateralgm.libmaker.backend.Action;
import org.lateralgm.libmaker.backend.Action.PAction;
import org.lateralgm.libmaker.backend.Argument;
import org.lateralgm.libmaker.backend.Argument.PArgument;
public class ActionPreview extends JInternalFrame implements ActionListener
{
private static final long serialVersionUID = 1L;
private ButtonGroup applies;
private JComboBox appliesObject;
private JPanel appliesPanel;
private ArgumentComponent argComp[];
private JCheckBox relativeBox;
private JCheckBox notBox;
private JButton save;
private JButton discard;
public static void showInFrame(Component parent, Action a)
{
final JFrame f = new JFrame();
ActionPreview ap = new ActionPreview(a);
ap.setVisible(true);
ap.addInternalFrameListener(new InternalFrameAdapter()
{
public void internalFrameClosed(InternalFrameEvent e)
{
f.dispose();
}
});
JDesktopPane dp = new JDesktopPane();
dp.add(ap);
f.add(dp);
f.setSize(ap.getSize());
f.setLocationRelativeTo(parent);
f.setVisible(true);
}
public ActionPreview(Action a)
{
super((String) a.get(PAction.DESCRIPTION),false,true,false,false);
BufferedImage img = a.get(PAction.IMAGE);
if (img != null) setFrameIcon(new ImageIcon(img.getScaledInstance(16,16,Image.SCALE_SMOOTH)));
String[] cao = {
Messages.getString("ActionPreview.APPLY_OBJ_SELF"),Messages.getString("ActionPreview.APPLY_OBJ_EX") }; //$NON-NLS-1$ //$NON-NLS-2$
appliesObject = new JComboBox(cao);
appliesObject.setEnabled(false);
appliesObject.setOpaque(false);
appliesPanel = new JPanel();
appliesPanel.setOpaque(false);
appliesPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc;
applies = new ButtonGroup();
JRadioButton button = new JRadioButton(Messages.getString("ActionPreview.APPLY_SELF"),true); //$NON-NLS-1$
button.setOpaque(false);
applies.add(button);
gbc = new GridBagConstraints();
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
appliesPanel.add(button,gbc);
button = new JRadioButton(Messages.getString("ActionPreview.APPLY_OTHER")); //$NON-NLS-1$
button.setOpaque(false);
applies.add(button);
gbc = new GridBagConstraints();
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
appliesPanel.add(button,gbc);
button = new JRadioButton(Messages.getString("ActionPreview.APPLY_OBJECT")); //$NON-NLS-1$
button.setHorizontalAlignment(JRadioButton.LEFT);
button.setOpaque(false);
button.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
boolean sel = ((JRadioButton) e.getSource()).isSelected();
appliesObject.setEnabled(sel);
}
});
applies.add(button);
gbc = new GridBagConstraints();
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
appliesPanel.add(button,gbc);
gbc = new GridBagConstraints();
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
gbc.insets = new Insets(0,2,0,6);
appliesPanel.add(appliesObject,gbc);
makeArgumentPane(a);
pack();
repaint();
}
public void makeArgumentPane(Action a)
{
setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));
JLabel lab;
JPanel pane;
pane = new JPanel();
pane.setBorder(new EmptyBorder(6,6,0,6));
pane.setLayout(new BorderLayout());
add(pane);
BufferedImage img = a.get(PAction.IMAGE);
if (img != null)
{
lab = new JLabel(new ImageIcon(img));
lab.setBorder(new EmptyBorder(16,16,16,20));
pane.add(lab,BorderLayout.LINE_START);
}
String s = Messages.getString("ActionPreview.APPLIES"); //$NON-NLS-1$
appliesPanel.setBorder(BorderFactory.createTitledBorder(s));
pane.add(appliesPanel);
if (!(Boolean) a.get(PAction.APPLY)) appliesPanel.setVisible(false);
argComp = new ArgumentComponent[a.get(PAction.ARG_NUM)];
if (argComp.length > 0)
{
pane = new JPanel();
pane.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(6,8,0,8),
BorderFactory.createTitledBorder((String) null)));
GroupLayout kvLayout = new GroupLayout(pane);
GroupLayout.SequentialGroup hGroup, vGroup;
GroupLayout.ParallelGroup keyGroup, valueGroup;
hGroup = kvLayout.createSequentialGroup();
vGroup = kvLayout.createSequentialGroup();
keyGroup = kvLayout.createParallelGroup(Alignment.TRAILING);
valueGroup = kvLayout.createParallelGroup();
hGroup.addGap(4);
hGroup.addGroup(keyGroup);
hGroup.addGap(6);
hGroup.addGroup(valueGroup);
hGroup.addGap(4);
kvLayout.setHorizontalGroup(hGroup);
kvLayout.setVerticalGroup(vGroup);
pane.setLayout(kvLayout);
add(pane);
vGroup.addGap(4);
for (int n = 0; n < argComp.length; n++)
{
Argument arg = a.arguments[n];
argComp[n] = new ArgumentComponent(arg);
lab = new JLabel((String) arg.get(PArgument.CAPTION));
Alignment al;
if (n == 0 && a.get(PAction.IFACE_KIND) == Action.InterfaceKind.ARROWS)
{
argComp[n].setEditor(new ArrowsEditor((String) arg.get(PArgument.DEF_VALUE)));
al = Alignment.CENTER;
}
else
{
Component c = argComp[n].getEditor();
c.setMaximumSize(new Dimension(240,20));
c.setPreferredSize(new Dimension(200,20));
c.setMinimumSize(new Dimension(160,20));
al = Alignment.BASELINE;
}
keyGroup.addComponent(lab);
valueGroup.addComponent(argComp[n].getEditor());
if (n > 0) vGroup.addGap(6);
GroupLayout.ParallelGroup argGroup = kvLayout.createParallelGroup(al);
argGroup.addComponent(lab).addComponent(argComp[n].getEditor());
vGroup.addGroup(argGroup);
}
vGroup.addGap(4);
}
pane = new JPanel();
pane.setLayout(new FlowLayout(FlowLayout.TRAILING));
add(pane);
if (a.get(PAction.RELATIVE))
{
relativeBox = new JCheckBox(Messages.getString("ActionPreview.RELATIVE")); //$NON-NLS-1$
pane.add(relativeBox);
}
if (a.get(PAction.QUESTION))
{
notBox = new JCheckBox(Messages.getString("ActionPreview.NOT")); //$NON-NLS-1$
pane.add(notBox);
}
pane = new JPanel();
pane.setLayout(new GridLayout(1,2,8,0));
pane.setBorder(new EmptyBorder(0,8,8,8));
add(pane);
s = Messages.getString("ActionPreview.SAVE"); //$NON-NLS-1$
save = new JButton(s,Messages.getIconForKey("ActionPreview.SAVE")); //$NON-NLS-1$
save.addActionListener(this);
pane.add(save);
s = Messages.getString("ActionPreview.DISCARD"); //$NON-NLS-1$
discard = new JButton(s,Messages.getIconForKey("ActionPreview.DISCARD")); //$NON-NLS-1$
discard.addActionListener(this);
pane.add(discard);
}
private class ArrowsEditor extends JPanel
{
private static final long serialVersionUID = 1L;
private JToggleButton[] arrows;
private final Dimension btnSize = new Dimension(32,32);
private final Dimension panelSize = new Dimension(96,96);
public ArrowsEditor(String val)
{
setLayout(new GridLayout(3,3));
arrows = new JToggleButton[9];
BufferedImage icons = Messages.getImageForKey("ActionPreview.ARROWS"); //$NON-NLS-1$
if (icons == null) icons = new BufferedImage(72,72,BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < 9; i++)
{
arrows[i] = new JToggleButton();
arrows[i].setIcon(new ImageIcon(icons.getSubimage(24 * (i % 3),24 * (i / 3),24,24)));
arrows[i].setMinimumSize(btnSize);
arrows[i].setPreferredSize(btnSize);
int p = (2 - (i / 3)) * 3 + i % 3;
if (val.length() > p) arrows[i].setSelected(val.charAt(p) == '1');
add(arrows[i]);
}
setMaximumSize(panelSize);
setPreferredSize(panelSize);
}
}
private class ColorSelect extends JTextField
{
private static final long serialVersionUID = 1L;
public ColorSelect(Color c)
{
super();
setSelectedColor(c);
}
public void setSelectedColor(Color c)
{
setBackground(c);
}
}
private class ArgumentComponent
{
private Argument arg;
private Component editor;
public ArgumentComponent(Argument arg)
{
this.arg = arg;
editor = makeEditor();
discard();
}
private JComponent makeEditor()
{
switch ((Argument.Kind) arg.get(PArgument.KIND))
{
case BOOLEAN:
final String[] sab = { Messages.getString("ActionPreview.ARG_BOOL_FALSE"), //$NON-NLS-1$
Messages.getString("ActionPreview.ARG_BOOL_TRUE") }; //$NON-NLS-1$
return new JComboBox(sab);
case MENU:
final String[] sam = ((String) arg.get(PArgument.MENU_OPTS)).split("\\|"); //$NON-NLS-1$
return new JComboBox(sam);
case COLOR:
return new ColorSelect(
convertGmColor(Integer.parseInt((String) arg.get(PArgument.DEF_VALUE))));
case SPRITE:
case SOUND:
case BACKGROUND:
case PATH:
case SCRIPT:
case OBJECT:
case ROOM:
case FONT:
case TIMELINE:
final String[] sar = {
Messages.getString("ActionPreview.ARG_RES_NONE"),Messages.getString("ActionPreview.ARG_RES_EX") }; //$NON-NLS-1$ //$NON-NLS-2$
return new JComboBox(sar);
default:
return new JTextField((String) arg.get(PArgument.DEF_VALUE));
}
}
public Component getEditor()
{
return editor;
}
public void setEditor(Component editor)
{
this.editor = editor;
}
public void discard()
{
if (editor instanceof JComboBox)
{
try
{
int val = Integer.parseInt((String) arg.get(PArgument.DEF_VALUE));
JComboBox cb = (JComboBox) editor;
if (val < 0 || val >= cb.getItemCount()) val = 0;
if (cb.getItemCount() == 0) val = -1;
((JComboBox) editor).setSelectedIndex(val);
}
catch (NumberFormatException e)
{
//fine, no selection then.
}
}
}
}
public static Color convertGmColor(int col)
{
return new Color(col & 0xFF,(col & 0xFF00) >> 8,(col & 0xFF0000) >> 16);
}
public static String getKindName(Argument.Kind k)
{
return k.name();
}
public void actionPerformed(ActionEvent evt)
{
doDefaultCloseAction();
}
}